package com.hunter.jerrymouse.server.netty;

import com.hunter.jerrymouse.request.RequestHandleContext;
import com.hunter.jerrymouse.server.Server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Created by hunter
 * <p>
 * 默认的服务实现, 这里用netty做的
 */
@Component
public class DefaultServer implements Server {

    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServer.class);

    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());

    @Autowired
    private RequestHandleContext requestHandleContext;

    public void beforeStart() {
        requestHandleContext.refreshRequestContext();
    }

    public void start(int port) throws Exception {
        LOGGER.info("Default server is starting.");

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new DefaultChannelHandler());

        // binder result,   TODO 端口: 命令行 >> 配置文件(未实现) >> 默认
        ChannelFuture cf = serverBootstrap.bind(port).await();

        if (!cf.isSuccess()) {
            LOGGER.error("Default server bind port failed : {}", port);
            start(port + 1);
        } else {
            LOGGER.info("Default server bind port success : {}", port);
        }
    }

    public void afterStart() {

    }

    public void shutDown() {
        bossGroup.shutdownGracefully().syncUninterruptibly();
        workerGroup.shutdownGracefully().syncUninterruptibly();

        LOGGER.info("Default server is shutdown.");
    }

    /**
     * 默认的handle添加处理
     */
    public class DefaultChannelHandler extends ChannelInitializer {

        @Override
        protected void initChannel(Channel channel) {
            ChannelPipeline pipeline = channel.pipeline();
            // 编码器
            // pipeline.addLast(new HttpRequestDecoder());
            // 解码器
            // pipeline.addLast(new HttpResponseEncoder());
            // 编解码
            pipeline.addLast(new HttpServerCodec());
            // HttpServerCodec解码 仍会调用多次channelRead方法, 一次是httpMessage, 多次httpContent, 可以用HttpObjectAggregator 将多个消息转换为单一的一个FullHttpRequest
            pipeline.addLast(new HttpObjectAggregator(65536));// 2的16次方
            // 处理器
            pipeline.addLast(new HttpRequestHandleServer());
        }
    }
}
